package cn.sylinx.horm.core;

import cn.sylinx.horm.core.datasource.ConnectionProvider;
import cn.sylinx.horm.core.datasource.TransactionalConnectionProvider;
import cn.sylinx.horm.exception.ErrorCodeRecordable;
import cn.sylinx.horm.exception.TransactionException;
import cn.sylinx.horm.transaction.jdbc.ITransactionBlock;
import cn.sylinx.horm.transaction.jdbc.TransactionSupport;
import cn.sylinx.horm.util.GLog;
import cn.sylinx.horm.util.Ret;

/**
 * jdbc 事务
 * 
 * @author johnhan
 *
 */
public class TransactionSupportOrmClient extends OrmClient implements TransactionSupport {
    @Override
    public Ret transaction(ITransactionBlock transaction) {
        ConnectionProvider connectionProvider = getConnectionProvider();
        if (!(connectionProvider instanceof TransactionalConnectionProvider)) {
            throw new TransactionException("不支持事务处理");
        }
        TransactionalConnectionProvider transactionalConnectionProvider = (TransactionalConnectionProvider) connectionProvider;
        // 开始事务
        startTransaction(transactionalConnectionProvider, transaction.transactionIsolation());
        try {
            Ret ret = transaction.run();
            if (ret.isSuccess()) {
                // 提交事务
                commitTransaction(transactionalConnectionProvider);
            } else {
                // 回滚事务
                rollbackTransaction(transactionalConnectionProvider);
            }
            return ret;
        } catch (Throwable t) {

            rollbackTransaction(transactionalConnectionProvider);

            int code = 500;
            if (ErrorCodeRecordable.class.isAssignableFrom(t.getClass())) {
                code = ((ErrorCodeRecordable) t).getCode();
            }
            GLog.error("事务处理异常", t);
            return Ret.error(code, t.getMessage(), t);
        }
    }

    public TransactionSupport getTransactionSupport() {
        return this;
    }

    @Override
    public String toString() {
        return "TransactionSupportOrmClient [DbType --> " + getDialect().getDbType().getValue()
                + ", DataSourceName --> " + getDataSourceName() + "]";
    }

    private void startTransaction(TransactionalConnectionProvider transactionalConnectionProvider, int isolationLevel) {
        transactionalConnectionProvider.startTransaction(isolationLevel);
    }

    private void commitTransaction(TransactionalConnectionProvider transactionalConnectionProvider) {
        transactionalConnectionProvider.commitTransaction();
    }

    private void rollbackTransaction(TransactionalConnectionProvider transactionalConnectionProvider) {
        try {
            transactionalConnectionProvider.rollbackTransaction();
        } catch (Exception e) {
            GLog.error("事务回滚异常", e);
        }
    }
}